//
// Created by Administrator on 2024/11/4.
//

#ifndef AI_PACS_JSONTOSTRUCT_H
#define AI_PACS_JSONTOSTRUCT_H


#include <iostream>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>
#include <nlohmann/json.hpp>
#include <stdexcept>


using json = nlohmann::json;

class JsonToStruct {
public:
    template <typename T>
    static void getMember(T& req, typename T::MemberPtr member,json& nameField ) {
        std::visit([&req, &nameField](auto&& memberPtr) {
                nameField = req.*memberPtr;
        }, member);
    }

    template<typename T>
    static void setMember(T &req, typename T::MemberPtr ptr, auto &&value) {
        std::visit([&req, value = std::forward<decltype(value)>(value)](auto memberPtr) {
            req.*memberPtr = value;
        }, ptr);
    }

    template<typename T>
    static T fromJson(const json &j) {
        T req;
        auto fieldMap = T::getFieldMap();
        for (const auto &[key, memberPtr]: fieldMap) {
            try {
                if (j.contains(key)) {
                    setMember(req, memberPtr, j[key]);
                } else {
                    throw std::runtime_error("Missing required field: " + key);
                }
            } catch (const std::exception &e) {
                std::cerr << "Error: " << e.what() << std::endl;
                throw;
            }
        }
        return req;
    }

    template<typename T>
    static json toJson(const T &req) {
        auto  object = json::object();
        auto fieldMap = T::getFieldMap();
        for (const auto &[key, memberPtr]: fieldMap) {
            try {
                getMember(req,memberPtr,object[key]);
            } catch (const std::exception &e) {
                throw std::runtime_error("Error serializing field '" + key + "': " +e.what());
            }
        }
        return object;
    }
};


#endif //AI_PACS_JSONTOSTRUCT_H
